﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Diagnostics;
using MeizuSDK.Core;
using MeizuSDK.Drawing;
using System.IO;
using System.Reflection;

namespace MeizuSDK.Presentation
{
    /// <summary>
    /// 提供 static 方法和属性以管理应用程序，例如启动和停止应用程序、处理 Windows 消息的方法和获取应用程序信息的属性。无法继承此类。
    /// </summary>
    public static class Application
    {
        #region 常量
        /// <summary>
        /// 程序启动时显示动画
        /// </summary>
        private const uint MZGP_APP_START_ANIMATION = 0x00000001;
        /// <summary>
        /// 程序退出时显示动画
        /// </summary>
        private const uint MZGP_APP_END_ANIMATION = 0x00000002;
        #endregion

        #region DllImport
        [DllImport("MZFCWrapper.dll")]
        private static extern IntPtr MzAppCtor(PreTranslateMessageFunc pPreTranslateMessageFunc);

        [DllImport("MZFCWrapper.dll")]
        private static extern bool ActivateApp([MarshalAs(UnmanagedType.LPWStr)]string pClassName);

        [DllImport("MZFCWrapper.dll")]
        private static extern void MzAppDispose(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern void MzAppRun(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern void MzAppDone(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern void MzAppEnableNeverQuit(IntPtr pObj, bool bNeverQuit);

        [DllImport("MZFCWrapper.dll")]
        private static extern bool MzAppIsEnableNeverQuit(IntPtr pObj);

        [DllImport("PlatformAPIWrapper.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool ShellNotifyMsgHoldShellUsingSomeKeyFunction(IntPtr hWnd, int uKeys);

        [DllImport("PlatformAPIWrapper.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool ShellNotifyMsgUnHoldShellUsingSomeKeyFunction(IntPtr hWnd);

        [DllImport("PlatformAPIWrapper.dll")]
        private static extern uint ShellNotifyGetShellNotifyMsg_AllKeyEvent();

        // API 函数
        [DllImport("MZFCWrapper.dll")]
        private static extern void MzBeginDisableMouseAPI();

        [DllImport("MZFCWrapper.dll")]
        private static extern void MzEndDisableMouseAPI();

        [DllImport("MZFCWrapper.dll")]
        private static extern bool MzIsDisableMouseAPI();

        [DllImport("MZFCWrapper.dll")]
        private static extern uint MzGetHomeKeyMessageAPI();

        [DllImport("PlatformAPIWrapper.dll")]
        private static extern uint CommonAPIMzGetParam(uint uParam);
        #endregion

        #region 事件
        /// <summary>
        /// 当任务栏可视性发生变化时，触发此事件
        /// </summary>
        public static event EventHandler TaskBarVisibleChanged;
        /// <summary>
        /// 当AutoRotateScreen属性被改变后
        /// </summary>
        internal static event EventHandler AutoRotateScreenChanged;
        #endregion

        #region 静态变量
        /// <summary>
        /// 应用程序实例对象
        /// </summary>
        private static IntPtr pObj;

        private static PreTranslateMessageFunc pPreTranslateMessageFunc;
        /// <summary>
        /// 应用程序唯一编号。用于程序启动唯一性验证
        /// </summary>
        internal static string appId;
        /// <summary>
        /// M键消息
        /// </summary>
        private static uint homeKeyMsg = uint.MaxValue;
        /// <summary>
        /// 是否显示任务栏
        /// </summary>
        private static bool isShowTaskBar = true;
        /// <summary>
        /// 是否竖屏显示
        /// </summary>
        private static bool isShowVerticle = true;
        /// <summary>
        /// 是否使用重力转屏
        /// </summary>
        private static bool autoRotateScreen;
        #endregion

        #region 静态属性
        /// <summary>
        /// 获取或设置一个标志，指示程序是否支持重力转屏
        /// </summary>
        public static bool AutoRotateScreen
        {
            get{
                return autoRotateScreen;
            }
            set{
                if(value!=autoRotateScreen)
                {
                    autoRotateScreen = value;

                    if(AutoRotateScreenChanged!=null)
                    {
                        AutoRotateScreenChanged(null, EventArgs.Empty);
                    }
                }
            }
        }
        /// <summary>
        /// 获取一个标志，指示程序是否正在运行
        /// </summary>
        internal static bool IsRunning
        {
            get;
            set;
        }
        /// <summary>
        /// 获取一个值，指示程序句柄是否创建
        /// </summary>
        internal static bool IsApplicationHandleCreated
        {
            get
            {
                return pObj != IntPtr.Zero;
            }
        }
        /// <summary>
        /// 获取HOME键的消息值
        /// </summary>
        internal static uint HomeKeyMessage
        {
            get
            {
                if (homeKeyMsg == uint.MaxValue)
                    homeKeyMsg = MzGetHomeKeyMessageAPI();

                return homeKeyMsg;
            }
        }
        /// <summary>
        /// 获取当前应用程序是否屏蔽了鼠标操作
        /// </summary>
        public static bool IsMouseDisabled
        {
            get
            {
                return MzIsDisableMouseAPI();
            }
        }
        /// <summary>
        /// 获取应用程序主窗口
        /// </summary>
        public static Form MainWindow
        {
            get;
            private set;
        }
        /// <summary>
        /// 获取或设置用户在按下M键后是否关闭应用程序
        /// </summary>
        public static bool IsNeverQuit
        {
            get
            {
                if (IsApplicationHandleCreated)
                    return MzAppIsEnableNeverQuit(pObj);
                else
                    return true;
            }
            set
            {
                if (IsApplicationHandleCreated)
                    MzAppEnableNeverQuit(pObj, value);
            }
        }
        /// <summary>
        /// 获取应用程序可执行文件的路径，不包含可执行文件名
        /// </summary>
        public static string StartupPath
        {
            get
            {
                return Path.GetDirectoryName(Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName);
            }
        }
        /// <summary>
        /// 获取或设置应用程序ID
        /// </summary>
        internal static string AppId
        {
            get
            {
                if (String.IsNullOrEmpty(appId))
                {
                    appId = Guid.NewGuid().ToString();
                }
                return appId;
            }
            set
            {
                if (value != appId)
                {
                    appId = value;
                }
            }
        }
        /// <summary>
        /// 获取程序是否显示任务栏
        /// </summary>
        public static bool IsShowTaskBar
        {
            get
            {
                return isShowTaskBar;
            }
            set
            {
                if (value != isShowTaskBar)
                {
                    isShowTaskBar = value;

                    ShowTaskBar(isShowTaskBar);
                }
            }
        }
        /// <summary>
        /// 获取一个标志，指示程序是否以垂直状态显示。false表示窗口为水平方向显示
        /// </summary>
        internal static bool IsShowVerticle
        {
            get
            {
                return isShowVerticle;
            }
        }
        /// <summary>
        /// 获取系统设置中是否启用了程序启动动画
        /// </summary>
        public static bool UseAppStartAnimation
        {
            get{
                uint i = CommonAPIMzGetParam(MZGP_APP_START_ANIMATION);

                return Convert.ToBoolean(i);
            }
        }
        /// <summary>
        /// 获取系统设置中是否启用了程序退出动画
        /// </summary>
        public static bool UseAppEndAnimation
        {
            get{
                uint i = CommonAPIMzGetParam(MZGP_APP_END_ANIMATION);

                return Convert.ToBoolean(i);
            }
        }
        #endregion

        #region 函数
        /// <summary>
        /// 根据指定标志确定是否显示任务栏
        /// </summary>
        /// <param name="bShow">true，表示显示任务栏；false表示隐藏任务栏</param>
        internal static void ShowTaskBar(bool bShow)
        {
            IntPtr hTaskBar = NativeMethods.FindWindowW("CTaskBar", string.Empty);

            if (hTaskBar != IntPtr.Zero)
            {
                NativeMethods.ShowWindow(hTaskBar, bShow ? NativeFormShowType.Show : NativeFormShowType.Hide);

                if (IsRunning && TaskBarVisibleChanged != null)
                {
                    TaskBarVisibleChanged(null, EventArgs.Empty);
                }
            }
        }
        /// <summary>
        /// 防鼠标误操作 API:
        /// 当一块代码需要耗较长时间处理时, 可以在它前面调用 BeginDisableMouse() , 
        /// 在它后面调用 EndDisableMouse()，即在它运行期间可防止程序响应用户的操作，起到防误操作的目的. 
        /// </summary>
        public static void BeginDisableMouse()
        {
            MzBeginDisableMouseAPI();
        }
        /// <summary>
        /// 防鼠标误操作 API: 
        /// 当一块代码需要耗较长时间处理时, 可以在它前面调用 BeginDisableMouse() , 
        /// 在它后面调用 EndDisableMouse()，即在它运行期间可防止程序响应用户的操作，起到防误操作的目的. 
        /// </summary>
        public static void EndDisableMouse()
        {
            MzEndDisableMouseAPI();
        }
        /// <summary>
        /// 如果已经存在应用程序实例则激活
        /// </summary>
        /// <returns>存在应用程序实例并激活成功返回true；否则返回false</returns>
        public static bool ActivatePreviousInstance()
        {
            return ActivatePreviousInstance(AppId);
        }
        /// <summary>
        /// 如果已经存在应用程序实例则激活
        /// </summary>
        /// <param name="appId">应用程序ID</param>
        /// <returns>存在应用程序实例并激活成功返回true；否则返回false</returns>
        public static bool ActivatePreviousInstance(string appId)
        {
            AppId = appId;
            return ActivateApp(appId);
        }

        /// <summary>
        /// 在当前线程上开始运行标准应用程序消息循环，并使指定窗体可见。
        /// </summary>
        /// <param name="window">要显示的窗口</param>
        public static void Run(Form window)
        {
            Run(window, true);
        }
        /// <summary>
        /// 在当前线程上开始运行标准应用程序消息循环，并使指定窗体可见。
        /// </summary>
        /// <param name="window">要显示的窗口</param>
        /// <param name="showTaskBar">是否显示任务栏</param>
        public static void Run(Form window, bool showTaskBar)
        {
            Run(window, showTaskBar, false);
        }
        /// <summary>
        /// 在当前线程上开始运行标准应用程序消息循环，并使指定窗体可见。
        /// </summary>
        /// <param name="window">要显示的窗口</param>
        /// <param name="isShowTaskBar">是否显示任务栏</param>
        /// <param name="isNeverQuit">在按下M键后是否保持窗口可见状态</param>
        public static void Run(Form window, bool isShowTaskBar, bool isNeverQuit)
        {
            pPreTranslateMessageFunc = new PreTranslateMessageFunc(PreTranslateMessage);
            pObj = MzAppCtor(pPreTranslateMessageFunc);

            IsRunning = true;
            // 点击M键是否退出程序
            IsNeverQuit = isNeverQuit;

            // 显示或隐藏任务栏
            IsShowTaskBar = isShowTaskBar;

            MainWindow = window;
            // 显示主窗口
            window.Show();

            MzAppRun(pObj);

            // 销毁主窗口资源
            if (window != null && !window.IsDisposed)
            {
                window.Dispose();
            }

            // 释放应用程序资源
            MzAppDone(pObj);
            // 删除应用程序实例
            MzAppDispose(pObj);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static uint PreTranslateMessage(MSG msg)
        {
            return 0;
        }
        /// <summary>
        /// 退出应用程序
        /// </summary>
        public static void Exit()
        {
            Exit(0);
        }
        /// <summary>
        /// 退出应用程序
        /// </summary>
        /// <param name="code"></param>
        public static void Exit(int code)
        {
            IsRunning = false;
            IsNeverQuit = false;

            if (!IsShowTaskBar)
                IsShowTaskBar = true;

            // 如果在程序退出时鼠标还是被禁用，则启用鼠标
            if (IsMouseDisabled)
            {
                EndDisableMouse();
            }
            // 关闭重力加速度传感器
            GravitySensor.Instance.Dispose();

            // 关闭主窗口
            if (MainWindow != null && !MainWindow.IsDisposed)
                MainWindow.Close();

            NativeMethods.PostQuitMessage(0);
        }
        #endregion
    }

    /// <summary>
    /// Windows 消息结构体
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public class MSG
    {
        public IntPtr hwnd;
        public int message;
        public IntPtr wParam;
        public IntPtr lParam;
        public int time;
        public int pt_x;
        public int pt_y;
    }
}
